package com.auto.video.tv;

import static com.xin.auto.lib.base.Contants.MONTH_ITEMS;
import com.auto.video.tv.serial.SerialPortControl;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.hardware.usb.UsbDevice;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.serialport.SerialPortFinder;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.MediaController;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.VideoView;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.fragment.app.FragmentActivity;
import com.auto.tv.serial.comn.Device;
import com.auto.tv.serial.comn.SerialPortManager;
import com.auto.tv.serial.comn.constant.PreferenceKeys;
import com.auto.tv.serial.comn.message.RecvMessage;
import com.auto.tv.serial.comn.utils.PrefHelper;
import com.auto.video.tv.presenter.IVideoPresenter;
import com.auto.video.tv.presenter.VideoPresenter;
import com.auto.video.tv.util.ByteUtil;
import com.auto.video.tv.serial.FlagManager;
import com.auto.video.tv.serial.SerialPortControl;
import com.auto.video.tv.widget.WeatherItemView;
import com.xin.auto.lib.base.CalendarUtils;
import com.xin.auto.lib.base.CommonUtils;
import com.xin.auto.lib.base.DateUtils;
import com.xin.auto.lib.base.DbHelper;
import com.xin.auto.lib.base.ExcelUtil;
import com.xin.auto.lib.base.Humans;
import com.xin.auto.lib.base.SharedPreferencesUtils;
import com.xin.auto.lib.base.UsbHelper;
import com.xin.auto.lib.base.adloopvideoplayer.receiver.UsbReceiver;
import com.xin.auto.lib.base.adloopvideoplayer.service.UsbService;
import com.xin.auto.lib.base.adloopvideoplayer.view.IView;
import com.yanzhenjie.permission.AndPermission;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import me.jahnen.libaums.core.fs.UsbFile;

public class MainActivity extends FragmentActivity implements View.OnClickListener,
        MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener, IView,
        UsbReceiver.UsbListener, AdapterView.OnItemSelectedListener {
    private static final String TAG = "MainActivity";
    private List<String> mMediaList = new ArrayList<>();

    private VideoView mVideoView;
    private ImageButton mImageButton;
    private LinearLayout mPeopleLayout;
    private Button mConfirmBtn;

    private TextView mCurrentTextView;
    private TextView mMonthTextView;
    private Spinner mSpinner;
    private Spinner mSpinnerDevices;
    private String mSelectMonth;

    protected AutoVideoApplication mApplication;
    private WeatherItemView mTemperature;
    private WeatherItemView mHumidity;
    private WeatherItemView mNGas;
    private WeatherItemView mHsGas;
    private WeatherItemView mIllumination;
    private SerialPortControl serialPortControl;

    public static String[] PERMISSIONS_STORAGE = {
            "android.permission.READ_EXTERNAL_STORAGE",
            "android.permission.WRITE_EXTERNAL_STORAGE",
            "android.permission.INTERNET",
            "android.permission.ACCESS_NETWORK_STATE",
            "android.permission.ACCESS_WIFI_STATE",
    };


    private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";

    // 人流量
    private int traffic = 0;
    // 温度
    private String temperature = "";
    // 湿度
    private String humidity = "";
    // 氨气
    private String ammonia = "";
    // 硫化氢
    private String hydrogen_sulfide = "";
    // 光照
    private String illumination = "";

    // 设置信息
    private boolean setInfoFlag = false;
    // 升级模式
    private boolean updateModeFlag = false;
    //收到升级包
    private boolean receiveDataFlag = false;

    private byte[] recvBuf = new byte[1024];

    private static final int RECEIVER_DATA = 0x1000;

    private IVideoPresenter mPresenter;

    private EditText mDevPathEditText;
    private String mSerialPath = "/dev/ttyS3";
    private Device mDevice;

    private int mDeviceIndex;
    private int mBaudrateIndex;

    private String[] mDevices;
    private String[] mBaudrates;

    private boolean mOpened = false;
    private UsbHelper mUsbHelper;

    private Handler mHandler = new Handler(new Handler.Callback() {
        @SuppressLint("NotifyDataSetChanged")
        @Override
        public boolean handleMessage(@NonNull Message msg) {
            if (msg.what == RECEIVER_DATA) {
                mCurrentTextView.setText(getString(R.string.app_current_peoples, String.valueOf(traffic)));
                mTemperature.setValueText(String.valueOf(temperature));
                mHumidity.setValueText(String.valueOf(humidity));
                mNGas.setValueText(String.valueOf(ammonia));
                mHsGas.setValueText(String.valueOf(hydrogen_sulfide));
                mIllumination.setValueText(String.valueOf(illumination));
            }
            return false;
        }
    });

    @SuppressLint("WrongConstant")
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate: ");
        mApplication = (AutoVideoApplication) AutoVideoApplication.getApplication();
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_main);
        mPresenter = new VideoPresenter(this);
        EventBus.getDefault().register(this);
        mUsbHelper = new UsbHelper(this, this);
        initDevice();
        initView();
        AndPermission.with(this)
                .runtime()
                .permission(PERMISSIONS_STORAGE)
                .onGranted(permissions -> {
                    mPresenter.getData(mUsbHelper);
                })
                .onDenied(permissions -> {
                    Toast.makeText(this, "没获取到sd卡权限，无法播放本地视频哦", Toast.LENGTH_LONG).show();
                })
                .start();
        initMediaPlayer();
        switchSettingMode(true);
    }

    /**
     * 初始化设备列表
     */
    private void initDevice() {
        SerialPortFinder serialPortFinder = new SerialPortFinder();

        // 设备
        mDevices = serialPortFinder.getAllDevicesPath();
        Log.i(TAG, "mDevices->>" + mDevices.length);
        if (mDevices.length == 0) {
            mDevices = new String[]{
                    getString(R.string.no_serial_device)
            };
        }
        // 波特率
        mBaudrates = getResources().getStringArray(R.array.baudrates);

        mDeviceIndex = PrefHelper.getDefault().getInt(PreferenceKeys.SERIAL_PORT_DEVICES, 0);
        mDeviceIndex = mDeviceIndex >= mDevices.length ? mDevices.length - 1 : mDeviceIndex;
        mBaudrateIndex = PrefHelper.getDefault().getInt(PreferenceKeys.BAUD_RATE, 0);

        mDevice = new Device(mSerialPath, "115200");
    }

    /**
     * 打开或关闭串口
     */
    private void openSeriesPort() {
        // 保存配置
        PrefHelper.getDefault().saveInt(PreferenceKeys.SERIAL_PORT_DEVICES, mDeviceIndex);
        PrefHelper.getDefault().saveInt(PreferenceKeys.BAUD_RATE, mBaudrateIndex);

        mOpened = SerialPortManager.instance().open(mDevice) != null;
        if (mOpened) {
            // heartBeatCheck();
            Toast.makeText(this, "成功打开串口", Toast.LENGTH_LONG).show();
        } else {
            Toast.makeText(this, "打开串口失败", Toast.LENGTH_LONG).show();
        }
    }

    private void heartBeatCheck() {
        int time_val = 3000;
        Runnable heartBeatRunnable = new Runnable() {
            @Override
            public void run() {
                while (true) {
                    Log.d(TAG, "进入心跳线程run");
                    String timeString = ByteUtil.hexTimeString();
                    serialPortControl.sendCommand(FlagManager.SEND_HEARTBEAT, "02" + timeString);
                    try {
                            Thread.sleep(time_val);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                }
            }
        };
    }

    private void printErrLog(byte recvBuf2, byte recvData) {
        if (recvBuf2 == (byte) 0xAF) {
            switch (recvData) {
                case 0x01:
                    Log.e(TAG, "异常内容：人流量传感器1异常");
                    break;
                case 0x02:
                    Log.e(TAG, "异常内容：人流量传感器2异常");
                    break;
                case 0x03:
                    Log.e(TAG, "异常内容：温湿度传感器1异常");
                    break;
                case 0x04:
                    Log.e(TAG, "异常内容：温湿度传感器2异常");
                    break;
                case 0x05:
                    Log.e(TAG, "异常内容：光照传感器1异常");
                    break;
                case 0x06:
                    Log.e(TAG, "异常内容：光照传感器2异常");
                    break;
                default:
                    break;
            }
        }
    }

    @SuppressLint("StringFormatInvalid")
    private void initView() {
        mVideoView = findViewById(R.id.video_view);
        mTemperature = findViewById(R.id.temperature);
        mHumidity = findViewById(R.id.humidity);
        mNGas = findViewById(R.id.n_gas);
        mHsGas = findViewById(R.id.hs_gas);
        mIllumination = findViewById(R.id.illumination);

        mSpinnerDevices = findViewById(R.id.dev_path);

        ArrayAdapter<String> deviceAdapter =
                new ArrayAdapter<>(this, R.layout.spinner_default_item, mDevices);
        deviceAdapter.setDropDownViewResource(R.layout.spinner_item);
        mSpinnerDevices.setAdapter(deviceAdapter);
        mSpinnerDevices.setOnItemSelectedListener(this);

        mPeopleLayout = findViewById(R.id.peoples_layout);
        mConfirmBtn = findViewById(R.id.setting_confirm);
        mConfirmBtn.setOnClickListener(this);
        mCurrentTextView = findViewById(R.id.current_peoples_num);
        mMonthTextView = findViewById(R.id.month_peoples);
        mMonthTextView.setText(getString(R.string.app_current_peoples, "300"));

        mImageButton = findViewById(R.id.weather_setting);
        mImageButton.setOnClickListener(this);

        mSpinner = findViewById(R.id.select_peoples_spinner);
        ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, MONTH_ITEMS);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        mSpinner.setAdapter(adapter);
        mSpinner.setSelection(DateUtils.getMonth() - 1);
        mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                mSelectMonth = MONTH_ITEMS[i];
                Log.d(TAG, "mSpinner onItemSelected" + i + ", " + mSelectMonth);
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {

            }
        });
    }

    private void setEditable(Boolean isEditable) {
        mTemperature.setFocusable(isEditable);
        mHumidity.setFocusable(isEditable);
        mNGas.setFocusable(isEditable);
        mHsGas.setFocusable(isEditable);
        mIllumination.setFocusable(isEditable);
    }

    private void initMediaPlayer() {
        mVideoView.setOnPreparedListener(mediaPlayer -> mediaPlayer.setOnVideoSizeChangedListener((mediaPlayer1, i, i1) -> {
            MediaController mediaController = new MediaController(MainActivity.this);
            mVideoView.setMediaController(mediaController);
            mediaController.setAnchorView(mVideoView);
        }));
        mVideoView.start();
    }

    @Override
    public void onClick(View view) {
        int viewId = view.getId();
        if (viewId == R.id.weather_setting) {
            setEditable(true);
            switchSettingMode(true);
        } else if (viewId == R.id.setting_confirm) {
            if (!TextUtils.isEmpty(mSerialPath)) {
                SharedPreferencesUtils sharedPreferencesUtils = SharedPreferencesUtils.init(MainActivity.this);
                sharedPreferencesUtils.putString(CommonUtils.SERIES_PATH, mSerialPath);
                openSeriesPort();
            }

            temperature = mTemperature.getText();
            humidity = mHumidity.getText();
            ammonia = mNGas.getText();
            hydrogen_sulfide = mHsGas.getText();
            illumination = mIllumination.getText();
            float temperature_f = Float.parseFloat(temperature);
            float humidity_f = Float.parseFloat(humidity);
            float ammonia_f = Float.parseFloat(ammonia);
            float hydrogen_sulfide_f = Float.parseFloat(hydrogen_sulfide);
            float illumination_f = Float.parseFloat(illumination);
            serialPortControl.sendSetInfo(temperature_f,humidity_f,ammonia_f,hydrogen_sulfide_f,illumination_f);
            setEditable(false);
            switchSettingMode(false);
        }
    }

    private void switchSettingMode(boolean isConfirmMode) {
        mSpinnerDevices.setVisibility(isConfirmMode ? View.VISIBLE : View.GONE);
        mConfirmBtn.setVisibility(isConfirmMode ? View.VISIBLE : View.GONE);
        mPeopleLayout.setVisibility(isConfirmMode ? View.GONE : View.VISIBLE);
    }

    private int mediaIndex = -1;

    @Override
    public void onCompletion(MediaPlayer mediaPlayer) {
        Log.d(TAG, "videos onCompletion");
        if (mMediaList != null && mMediaList.size() > 0) {
            mediaIndex++;
        }
        if (mediaIndex >= mMediaList.size()) {
            mediaIndex = 0;
        }
        if (mediaIndex < 0) {
            return;
        }
        mVideoView.setVideoPath(mMediaList.get(mediaIndex));
        mVideoView.start();
    }

    @Override
    public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
        mVideoView.setVideoPath(mMediaList.get(mediaIndex));
        mVideoView.start();
        Toast.makeText(MainActivity.this, "播放错误", Toast.LENGTH_LONG).show();
        return false;
    }

    /**
     * 用EventBus进行线程间通信，也可以使用Handler
     */
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onEventMainThread(RecvMessage msg) {
        Log.i(TAG,"获取到了从传感器发送到Android主板的串口数据:" + msg);
        recvBuf = ByteUtil.toByteArray(msg.getMessage());
        int serialNum = 255;
        if (recvBuf[0] == (byte) 0x10 && recvBuf[3] != (byte) (serialNum & 0xFF)){
            heartBeatCheck();
            serialNum = recvBuf[3];
            if (recvBuf[2] == (byte) 0xA0 && recvBuf[4] == (byte) 0x15) {
                traffic += (recvBuf[5] & 0xFF);
                temperature = ByteUtil.convertDoubleToStr(((ByteUtil.hexByteTofloat(recvBuf[6], recvBuf[7],100)
                        + ByteUtil.hexByteTofloat(recvBuf[16], recvBuf[17],100)) * 0.5), "0.00");
                humidity = ByteUtil.convertDoubleToStr(((ByteUtil.hexByteTofloat(recvBuf[8], recvBuf[9],100)
                        + ByteUtil.hexByteTofloat(recvBuf[18], recvBuf[19],100)) * 0.5), "0.00");
                ammonia = ByteUtil.convertDoubleToStr(((ByteUtil.hexByteTofloat(recvBuf[10], recvBuf[11],1000)
                        + ByteUtil.hexByteTofloat(recvBuf[20], recvBuf[21],1000)) * 0.5), "0.000");
                hydrogen_sulfide = ByteUtil.convertDoubleToStr(((ByteUtil.hexByteTofloat(recvBuf[12], recvBuf[13],1000)
                        + ByteUtil.hexByteTofloat(recvBuf[22], recvBuf[23],1000)) * 0.5), "0.000");
                illumination = ByteUtil.convertDoubleToStr(((ByteUtil.hexByteTofloat(recvBuf[14], recvBuf[15],1)
                        + ByteUtil.hexByteTofloat(recvBuf[24], recvBuf[25],1)) * 0.5), "0");
                mHandler.sendEmptyMessage(RECEIVER_DATA);
            }
            // 设置成功
            setInfoFlag = recvBuf[2] == (byte) 0xA1 && recvBuf[5] == (byte) 0x02;
            updateModeFlag = recvBuf[2] == (byte) 0xA2 && recvBuf[5] == (byte) 0x02;
            receiveDataFlag = recvBuf[2] == (byte) 0xA3 && recvBuf[7] == (byte) 0x02;
            serialNum ++;
            if (serialNum > 255) {
                serialNum = 0;
            }
            printErrLog(recvBuf[2], recvBuf[5]);
        }

        if (traffic % 100 == 0) {
            DbHelper dbHelper = new DbHelper(getApplicationContext());
            Humans humans = new Humans(String.valueOf(CalendarUtils.getMonth() + 1), traffic);
            dbHelper.insert(humans);
        }

        if (CalendarUtils.isOClock()) {
            new Thread(() -> ExcelUtil.getInstance().exportExcel(getApplicationContext(), mUsbHelper, progress -> {
                if (progress >= 99) {
                    runOnUiThread(() -> Toast.makeText(getApplicationContext(), "导出成功!", Toast.LENGTH_LONG).show());
                }
            })).start();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        Intent service = new Intent(this, UsbService.class);
        startService(service);
    }

    @Override
    protected void onDestroy() {
        SerialPortManager.instance().close();
        mUsbHelper.finishUsbHelper();
        super.onDestroy();
    }

    @Override
    public void showData(List<UsbFile> data) {
        if (data == null || data.size() <= 0) {
            Toast.makeText(MainActivity.this, "无法读取视频列表", Toast.LENGTH_LONG).show();
            return;
        }
        for (UsbFile usbFile:data) {
            copyUSbFile(usbFile);
        }
    }

    @Override
    public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) {
        mSerialPath = mDevices[mDeviceIndex];
        mDeviceIndex = position;
        mDevice.setPath(mDevices[mDeviceIndex]);
    }

    @Override
    public void onNothingSelected(AdapterView<?> adapterView) {

    }

    @Override
    public void insertUsb(UsbDevice device_add) {
        Log.i(TAG, "insertUsb");
    }

    @Override
    public void removeUsb(UsbDevice device_remove) {
        Log.i(TAG, "removeUsb");
    }

    @Override
    public void getReadUsbPermission(UsbDevice usbDevice) {
        Log.i(TAG, "getReadUsbPermission");
    }

    @Override
    public void failedReadUsb(UsbDevice usbDevice) {
        Log.i(TAG, "failedReadUsb");
    }

    @Override
    public void onPointerCaptureChanged(boolean hasCapture) {

    }

    private String localCurrentPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();
    /**
     * 复制 USB 文件到本地
     *
     * @param file USB文件
     */
    private void copyUSbFile(final UsbFile file) {
        //复制到本地的文件路径
        final String filePath = localCurrentPath + File.separator + file.getName();
        File mediaFile = new File(filePath);
        if (mediaFile.exists() && mediaFile.length() > 0) {
            mMediaList.add(filePath);
            mediaIndex = 0;
            mVideoView.setVideoPath(mMediaList.get(0));
            return;
        }
        new Thread(new Runnable() {
            @Override
            public void run() {
                //复制结果
                final boolean result = mUsbHelper.saveUSbFileToLocal(file, filePath, new UsbHelper.DownloadProgressListener() {
                    @Override
                    public void downloadProgress(final int progress) {

                    }
                });
                //主线程更新UI
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if (result) {
                            mMediaList.add(filePath);
                            mediaIndex = 0;
                            mVideoView.setVideoPath(mMediaList.get(0));
                        } else {
                            Toast.makeText(MainActivity.this, "复制失败", Toast.LENGTH_SHORT).show();
                        }
                    }
                });
            }
        }).start();
    }
}